package com.tbit.uqbike.webmanager.util.weixin;

import com.tbit.uqbike.constant.WeixinConstant;
import com.tbit.uqbike.webmanager.util.http.HttpClientConnectionManager;
import com.tbit.uqbike.webmanager.util.redis.RedisUtil;
import com.tbit.uqbike.webmanager.util.spring.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import javax.net.ssl.SSLContext;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
public class GetWxOrderno {

    /**
     * 获取client实例
     */
    private static synchronized DefaultHttpClient getClient() {
        DefaultHttpClient client = new DefaultHttpClient();
        client = (DefaultHttpClient) HttpClientConnectionManager.getSSLInstance(client);

        return client;
    }

    /**
     * description:获取预支付id
     *
     * @param url
     * @param xmlParam
     * @return
     * @author ex_yangxiaoyi
     * @see
     */
    @SuppressWarnings("unchecked")
    public static String getPayNo(String url, String xmlParam) {
        DefaultHttpClient client = new DefaultHttpClient();
        client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
        HttpPost httpost = HttpClientConnectionManager.getPostMethod(url);
        String prepay_id = "";
        try {
            httpost.setEntity(new StringEntity(xmlParam, "UTF-8"));
            HttpResponse response = getClient().execute(httpost);
            String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
            if (jsonStr.indexOf("FAIL") != -1) {
                /**调试打印*/
                log.info("微信支付调试：" + jsonStr);
                return prepay_id;
            }
            Map map = doXMLParse(jsonStr);
            prepay_id = (String) map.get("prepay_id");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return prepay_id;
    }

    /**
     * 退款接口
     *
     * @param
     * @param url
     * @param out_trade_no
     */
    public static Boolean return_deposit(String accountId, Integer type, String url, String xml, String parner, String out_trade_no) {
        try {
            KeyStore keyStore = KeyStore.getInstance("PKCS12");

            String certPath = String.format(WeixinConstant.deposit_return_app_path, accountId);
            if (type == 2) {
                certPath = String.format(WeixinConstant.deposit_return_weixin_path, accountId);
            }

            FileInputStream instream = new FileInputStream(new File(certPath));
            try {
                keyStore.load(instream, parner.toCharArray());
            } finally {
                instream.close();
            }
            SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, parner.toCharArray()).build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
            CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

            HttpPost httpost = HttpClientConnectionManager.getPostMethod(url);
            httpost.setEntity(new StringEntity(xml, "UTF-8"));
            HttpResponse weixinResponse = httpClient.execute(httpost);
            String jsonStr = EntityUtils.toString(weixinResponse.getEntity(), "UTF-8");
            log.info("\n" + jsonStr);

            Map map = GetWxOrderno.doXMLParse(jsonStr);
            log.info("退款接口回调参数{}" + map);

            if ("success".equalsIgnoreCase((String) map.get("result_code"))) {
                log.info("退款成功");
                return true;
            } else {
                log.error("退款失败=" + map.get("result_msg"));
                //退款失败将错误信息保存redis五分钟
                RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class);
                redisUtil.setEx(com.tbit.uqbike.webmanager.util.RedisUtil.getRefundHashId(out_trade_no), (String) map.get("return_msg"), 5, TimeUnit.MINUTES);
                return false;
            }
        } catch (Exception e) {
            log.error("退款异常", e);
        }

        return false;
    }

    /**
     * description:获取扫码支付连接
     *
     * @param url
     * @param xmlParam
     * @return
     * @author ex_yangxiaoyi
     * @see
     */
    @SuppressWarnings("unchecked")
    public static String getCodeUrl(String url, String xmlParam) {
        DefaultHttpClient client = new DefaultHttpClient();
        client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
        HttpPost httpost = HttpClientConnectionManager.getPostMethod(url);
        String code_url = "";
        try {
            httpost.setEntity(new StringEntity(xmlParam, "UTF-8"));
            HttpResponse response = getClient().execute(httpost);
            String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
            if (jsonStr.indexOf("FAIL") != -1) {
                return code_url;
            }
            Map map = doXMLParse(jsonStr);
            code_url = (String) map.get("code_url");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return code_url;
    }

    /**
     * 解析xml,返回第一级元素键值对。如果第一级元素有子节点，则此节点的值是子节点的xml数据。
     *
     * @param strxml
     * @return
     * @throws JDOMException
     * @throws IOException
     */
    public static Map doXMLParse(String strxml) throws Exception {
        if (null == strxml || "".equals(strxml)) {
            return null;
        }

        Map m = new HashMap();
        InputStream in = String2Inputstream(strxml);
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(in);
        Element root = doc.getRootElement();
        List list = root.getChildren();
        Iterator it = list.iterator();
        while (it.hasNext()) {
            Element e = (Element) it.next();
            String k = e.getName();
            String v = "";
            List children = e.getChildren();
            if (children.isEmpty()) {
                v = e.getTextNormalize();
            } else {
                v = getChildrenText(children);
            }

            m.put(k, v);
        }

        // 关闭流
        in.close();

        return m;
    }

    /**
     * 获取子结点的xml
     *
     * @param children
     * @return String
     */
    public static String getChildrenText(List children) {
        StringBuffer sb = new StringBuffer();
        if (!children.isEmpty()) {
            Iterator it = children.iterator();
            while (it.hasNext()) {
                Element e = (Element) it.next();
                String name = e.getName();
                String value = e.getTextNormalize();
                List list = e.getChildren();
                sb.append("<" + name + ">");
                if (!list.isEmpty()) {
                    sb.append(getChildrenText(list));
                }
                sb.append(value);
                sb.append("</" + name + ">");
            }
        }

        return sb.toString();
    }

    public static InputStream String2Inputstream(String str) {
        return new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
    }

}